smake::get_os_id() {
    local os_id=$(cat /etc/os-release | grep "ID" | cut -d "=" -f2 | tr -d '"')
    echo "$os_id"
}

smake::array_index_of() {
    local key=$1
    shift
    local array=("$@")
    for i in "${!array[@]}"; do
        if [[ "${array[$i]}" == "$key" ]]; then
            echo "$i"
            return
        fi
    done
    echo -1
}
smake::path_of() {
    local arg=$1
    local path=$(which "$arg")
    echo "$path"
}

smake::path_of_gcc() {
    smake::path_of "gcc"
}

smake::path_of_clang() {
    smake::path_of "clang"
}

smake::get_system_arch() {
    local arch=$(uname -m)
    echo "$arch"
}

# 基于 gcc 的编译系统
smake::get_gcc_support() {
    local gcc_path=$(smake::path_of_gcc)
    if [[ "$gcc_path" != "" ]]; then
        echo "true"
    else
        echo "false"
    fi
}

# 根据指定源文件获取编译命令
smake::get_compile_command() {
    local src_file=$1
    local compile_command=""
    if [[ "$(smake::get_gcc_support)" == "true" ]]; then
        compile_command="gcc -o ${src_file%.*} ${src_file}"
    else
        compile_command="clang -o ${src_file%.*} ${src_file}"
    fi
    echo "$compile_command"
}

smake::get_compile_command_with_flags() {
    local src_file=$1
    local compile_command=$(smake::get_compile_command "$src_file")
    local compile_flags=$2
    local compile_command_with_flags="$compile_command $compile_flags"
    echo "$compile_command_with_flags"
}


# 输入文件名，返回文件后缀
smake::get_file_suffix() {
    local file_name=$1
    local file_suffix=$(echo "$file_name" | awk -F "." '{print $NF}')
    echo "$file_suffix"
}

# 判断输入的文件后缀，如果是 c 或 cpp，则返回 true
smake::is_c_or_cpp_file() {
    # get_file_suffix
    local file_suffix=$(smake::get_file_suffix $1)
    local is_c_or_cpp="false"
    if [[ "$file_suffix" == "c" || "$file_suffix" == "cpp" ]]; then
        is_c_or_cpp="true"
    fi
    echo "$is_c_or_cpp"
}

# 对给定的文件进行编译
    # 如果是 c 则使用 gcc 编译出目标
smake::compile_file() {
    local src_file=$1
    if [[ "$(smake::is_c_or_cpp_file "$src_file")" == "true" ]]; then
        local compile_command=$(smake::get_compile_command "$src_file")
        local compile_command_with_flags=$(smake::get_compile_command_with_flags "$src_file" "$2")
        eval "$compile_command_with_flags"
    else
        # eval "$compile_command"
        echo "不支持的文件类型"
    fi
}

smake::get_all_files_in_dir() {
    local dir=$1
    local files=$(ls "$dir")
    echo "$files"
}

# 让 shell 可以在 Windows 下运行
function smake::win_path_to_unix() {
    local path=
    local unix_path=$(echo "$path" | sed 's/\\/\//g')
    echo "$unix_path"
}

function smake::unix_path_to_win() {
    local path=
    local win_path=$(echo "$path" | sed 's/\//\\/g')
    echo "$win_path"
}

function smake::get_current_dir() {
    local current_dir=$(pwd)
    echo "$current_dir"
}


# 获取一个 shell 脚本中所有函数定义的名字
function smake::get_all_function_names() {
    local script_path=$1
    local function_names=$(cat "$script_path" | grep "^function " | awk '{print $2}')
    echo "$function_names"
}
# 获取一个 shell 脚本中所有 smake:: 开头的 函数定义的名字
function smake::get_all_smake_function_names() {
    local script_path=$1
    local parttern="^smake::"
    local function_names=$(cat "$script_path" | grep "$parttern" | awk '{print $1}' | tr -d '(' | tr -d ')' )

    # local function_names=$(cat "$script_path" | grep "^smake::" | awk '{print $2}')
    echo "$function_names"
}




# 生成补全
function smake::generate_completion() {
    # comgen
}



smake() {
    local args=("$@")

}

# smake 命令调试环境变量
# 如果此环境变量被设置将会打印命令在补全时的调试信息
_smake_debug() {
    # 使用 BASH_COMP_YWLOADER_DEBUG_FILE 指定的文件进行输出调试信息
    #          v 如果在 bash 命令行中定义了这个环境变量，将传入本函数的所有内容输出(追加)到调试文件
    if [[ -n ${BASH_COMP_SMAKE_DEBUG_FILE:-} ]]; then
        echo "$@" >> "${BASH_COMP_SMAKE_DEBUG_FILE}"
    fi
}

_smake_debug_clean() {
    # 清空调试文件
    if [[ -n ${BASH_COMP_SMAKE_DEBUG_FILE:-} ]]; then
        echo "" > "${BASH_COMP_SMAKE_DEBUG_FILE}"
    fi
}

# bash completion
_smake() {
    # local command=${args[0]}
    # local words=("${COMP_WORDS[@]}")
    # local cword=${COMP_WORDS[COMP_CWORD]}
    # local cur=${COMP_WORDS[COMP_CWORD]}
    # local prev=${COMP_WORDS[COMP_CWORD-1]}
    _ywloader_debug_clean

    local cur prev words cword
    _init_completion || return

    _smake_debug "========== _smake function env ============"
    _smake_debug "_smake words: " "%${words[*]}%" "-- 所有词"
    _smake_debug "_smake prev:  " "%${prev}%"     "-- 前词"
    _smake_debug "_smake cur:   " "%${cur}%"      "-- 当前词"
    _smake_debug "_smake cword: " "%${cword}%"    "-- 位置引用"
    _smake_debug
    _smake_debug "_smake binary: " "%${words[0]}%"  "-- 当前程序"
    _smake_debug "_smake command:" "%${words[1]}%" "-- 当前子命令" 
    _smake_debug "========== _smake function env ============"
    _smake_debug ""

    local smake_help_commands=(
        build
        clean
        help
        init
        install
        list
        run
        update
    )

    local smake_commands=(
        help
        ${smake_help_commands[*]}
    )

    COMPREPLY=()

    if [[ ${cword} -eq 1 ]]; then
        # COMPREPLY=($(compgen -W "${smake_commands[*]}" -- "${cur}"))
        local smake_command="${words[1]}"
        COMPREPLY=($(compgen -W "${smake_commands[*]}" -- "${smake_command}"))
    elif [[ ${cword} -gt 1 ]]; then
        local smake_command="${words[1]}"
        # local smake_command_help_commands=()
        case "${smake_command}" in
            *)
                ;;
        esac
    fi
                
}

complete -F _smake smake